//===============================================================================
// Microsoft Architecture Strategy Team
// LitwareHR - SaaS Sample Application
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================


//===============================================================================
// Microsoft Architecture Strategy Team
// LitwareHR - S+S Sample Application
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.Windows.Forms;
using LitwareHR.Infrastructure.Interface;
using LitwareHR.PublicApp.WinUX.Constants;

using LitwareHR.PublicApp.WinUX.Services;

using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.Commands;
using Microsoft.Practices.CompositeUI.WPF;
using Microsoft.Practices.CompositeUI.EventBroker;
using Microsoft.Practices.ObjectBuilder;
using Microsoft.Practices.SmartClient.ConnectionMonitor;
using Microsoft.Practices.SmartClient.ConnectionMonitor.Implementations;

using LitwareHR.PublicApp.WinUX.DSA;
using LitwareHR.PublicApp.WinUX.Security.BrokeredSender;

using System.Threading;
using System.Configuration;

using LitwareHR.Infrastructure.Interface.Constants;
   
namespace LitwareHR.PublicApp.WinUX
{
    public class ModuleController : WorkItemController
    {
        private AuthenticationService authService;
        private TenantBrandingService tenantBrandingService;
        private RecruitingService recruitingService;
        private ConnectionMonitor connectionMonitor;
        private DefSynchronizationService defSynchronizationService;
        private RequestsManagerService requestsManagerService;
        private OfflineDataService offlineService;

        [InjectionConstructor]
        public ModuleController()
        {
        }
        
        /// <summary>
        /// 
        /// </summary>
        public override void Run()
        {
            AddBaseServices();

            //Not authn, just return with the empty Shell
            if( !Authenticate() )
                return;

            AddServices();

            ExtendMenu();
            ExtendToolStrip();

            InitializeServices();
            
            AddViews();

            StartDispatchingRequests();
        }

        private bool Authenticate()
        {
            return authService.Authenticate();
        }

        //Loads services needed for Authentication
        private void AddBaseServices()
        {
            WorkItem.Services.AddNew<ServiceProxy.UnSecure.AuthenticationService>();
            WorkItem.Services.AddNew<ServiceProxy.UnSecure.SystemService>();
            authService = WorkItem.Services.AddNew<AuthenticationService>(); 
        }

        /// <summary>
        /// 
        /// </summary>
        private void AddServices()
        {
            requestsManagerService = WorkItem.Services.AddNew<RequestsManagerService>();
            connectionMonitor = WorkItem.Services.Get<ConnectionMonitor>();

            //Disconnected Agent Application Block Agents
            WorkItem.Services.AddNew<DSA.Secure.ProcessService.Agent>();
            WorkItem.Services.AddNew<DSA.Secure.DataModelService.Agent>();
            WorkItem.Services.AddNew<DSA.UnSecure.DataModelService.Agent>();
            WorkItem.Services.AddNew<DSA.UnSecure.ProcessService.Agent>();            

            // Low level services that interact with the Web Proxies (channels)
            WorkItem.Services.AddNew<ServiceProxy.UnSecure.DataModelService>();
            WorkItem.Services.AddNew<ServiceProxy.UnSecure.PresentationService>();

            // Service for managing the local DB
            WorkItem.Services.AddNew<DBService>();
            offlineService = WorkItem.Services.AddNew<OfflineDataService>();

            WorkItem.Services.AddNew<ProcessService>();
            // The Recruiting Service is the "Model" in this app. Used by all Presenters in the Module.
            recruitingService = WorkItem.Services.AddNew<RecruitingService>();

            // Service for synchronizing local View & Entity definitions
            defSynchronizationService = WorkItem.Services.AddNew<DefSynchronizationService>();
            tenantBrandingService = WorkItem.Services.AddNew<TenantBrandingService>();
            WorkItem.Services.AddNew<RolesIconService>();
        }

        /// <summary>
        /// 
        /// </summary>
        private void ExtendMenu()
        {
            ToolStripMenuItem litwareItem = new ToolStripMenuItem(UIExtensionSiteNames.Litware);
            WorkItem.UIExtensionSites[UIExtensionSiteNames.MainMenu].Add(litwareItem);
            WorkItem.UIExtensionSites.RegisterSite(UIExtensionSiteNames.LitwareMenu, litwareItem.DropDownItems);

            UIExtensionSite litwareMenu = WorkItem.UIExtensionSites[UIExtensionSiteNames.LitwareMenu];
            
            AddUIExtension(WorkItem, litwareMenu, UIExtensionSiteNames.AppMenu, CommandNames.OnShowCareers, "Click");
            if (connectionMonitor.Connections[0].ConnectionTypeName.Equals("DesktopConnection"))
            {
                AddUIExtension(WorkItem, litwareMenu, UIExtensionSiteNames.Connect, CommandNames.OnForceConnect, "Click");
                AddUIExtension(WorkItem, litwareMenu, UIExtensionSiteNames.Disconnect, CommandNames.OnForceDisconnect, "Click");
            }
            AddUIExtension(WorkItem, litwareMenu, UIExtensionSiteNames.DBCleanUp, CommandNames.OnDBCleanUp, "Click");            

            if (connectionMonitor.IsConnected)
            {
                WorkItem.Commands[CommandNames.OnForceDisconnect].Status = CommandStatus.Enabled;
                WorkItem.Commands[CommandNames.OnForceConnect].Status = CommandStatus.Disabled;
            }
            else
            {
                WorkItem.Commands[CommandNames.OnForceDisconnect].Status = CommandStatus.Disabled;
                WorkItem.Commands[CommandNames.OnForceConnect].Status = CommandStatus.Enabled; 
            }
        }

        private static ToolStripItem AddUIExtension(WorkItem workItem, UIExtensionSite parent, string uiExtensionSiteName, string commandName, string uiEvent)
        {
            ToolStripMenuItem toolStripItem = new ToolStripMenuItem(uiExtensionSiteName);
            parent.Add(toolStripItem);
            workItem.UIExtensionSites.RegisterSite(uiExtensionSiteName, toolStripItem);
            if (commandName != null)
            {
                workItem.Commands[commandName].AddInvoker(toolStripItem, uiEvent);
            }
            return toolStripItem;
        }

        /// <summary>
        /// 
        /// </summary>
        private static void ExtendToolStrip()
        {
        }

        /// <summary>
        /// Start all Services
        /// </summary>
        private void InitializeServices()
        {
            defSynchronizationService.Initialize();
            tenantBrandingService.Initialize();
            recruitingService.Initialize();
        }

        private void StartDispatchingRequests()
        {
            //Start dispatching of pending and new requests
            requestsManagerService.StartDispatching();
        }
                
        /// <summary>
        /// 
        /// </summary>
        private void AddViews()
        {
            if (authService.IsAuthenticated())
            {
                WorkItem.Commands[CommandNames.OnShowCareers].Status = CommandStatus.Unavailable;    
                ShowViewInWorkspace<LinkView>(WorkspaceNames.LeftWorkspace);
                ShowViewInWorkspace<DefaultView>(WorkspaceNames.RightWorkspace);
                ShowViewInWorkspace<HeaderView>(WorkspaceNames.TopWorkspace);
            }        
        }

        [EventSubscription(EventTopicNames.ShowJobSearchView, ThreadOption.UserInterface)]
        public void OnShowJobSearchView(object sender, EventArgs eventArgs)
        {
             ShowViewInWorkspace<JobSearchView>(WorkspaceNames.RightWorkspace);
        }
        
        [EventSubscription(EventTopicNames.ShowOpenPositionView, ThreadOption.UserInterface)]
        public void OnShowOpenPositionView(object sender, EventArgs eventArgs)
        {
            ShowViewInWorkspace<OpenPositionView>(WorkspaceNames.RightWorkspace);            
        }        
             
        [EventSubscription(EventTopicNames.ShowDefaultView, ThreadOption.UserInterface)]
        public void OnShowDefaultView(object sender, EventArgs eventArgs)
        {
            ShowViewInWorkspace<DefaultView>(WorkspaceNames.RightWorkspace);
        }

        [EventSubscription(EventTopicNames.ShowCandidatesView, ThreadOption.UserInterface)]
        public void OnShowCandidatesView(object sender, EventArgs eventArgs)
        {
            ShowViewInWorkspace<CandidatesView>(WorkspaceNames.RightWorkspace);
        }

        [EventSubscription(EventTopicNames.Authenticate, ThreadOption.UserInterface)]
        public void SecurityAuthentication(object sender, EventArgs e)
        {
            authService.Authenticate();
        }
        
        [CommandHandler(CommandNames.OnShowCareers)]
        public void OnShowCareers(object sender, EventArgs e)
        {
            AddViews(); 
        }      

        /// <summary>
        /// These handlers will force connection and disconnection from the network.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        [CommandHandler(CommandNames.OnForceDisconnect)]
        public void OnForceDisconnect(object sender, EventArgs e)
        {
            DesktopConnection desktopConnection = (DesktopConnection)connectionMonitor.Connections[0];
            desktopConnection.Disconnect();
            WorkItem.Commands[CommandNames.OnForceDisconnect].Status = CommandStatus.Disabled;
            WorkItem.Commands[CommandNames.OnForceConnect].Status = CommandStatus.Enabled;
        }

        [CommandHandler(CommandNames.OnForceConnect)]
        public void OnForceConnect(object sender, EventArgs e)
        {
            DesktopConnection desktopConnection = (DesktopConnection)connectionMonitor.Connections[0];
            desktopConnection.Connect();
            WorkItem.Commands[CommandNames.OnForceDisconnect].Status = CommandStatus.Enabled ;
            WorkItem.Commands[CommandNames.OnForceConnect].Status = CommandStatus.Disabled;
        }

        [CommandHandler(CommandNames.OnDBCleanUp)]
        public void OnDBCleanUp(object sender, EventArgs e)
        {
            offlineService.CleanLocalDB();
            defSynchronizationService.SynchAllModels();
        }
    }
}
